﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using GMap.NET;
using GMap.NET.MapProviders;
using GMap.NET.WindowsPresentation;
using System.Drawing;
using System.Runtime.Serialization;
using System.Diagnostics;
using System.Data;
using System.Windows.Controls.Primitives;
using System.ComponentModel;
using ElStationUI.ManagementServiceReference;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Threading;

namespace ElStationUI
{
    /// <summary>
    /// Interaction logic for Main.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        IList<Station> allStations;
        IList<BatteryType> allBatteryTypes;
        //IList<UserAccount> allUserAccounts;
        IList<EmployeeAccount> allEmployeeAccounts;
        IList<UserAccount> allUserAccounts;
        IList<BatteryReservation> allReservations;
        EmployeeAccount usedAccount;
        private DispatcherTimer refreshTimer;

        #region BatteryTab variables

        double lastWorkingPercentage = 0;
        private GUIState availableBatteriesTabState;

        #endregion


        #region StationTab variables

        private bool draggingStation;   //are we currently dragging a newly added station
        IList<GMapMarker> allMarkers = new List<GMapMarker>();    //please use interfaces wherever you can, they don't hurt and you make a habbit of it
        private GMapMarker currentMarker;   //keep track of what you are adding/editing
        private string originalName;    //to make edit cancels possible
        private string markerName;     //this allows specifing name before actually adding a marker to the map
        private GUIState stationTabState;    //it let's all other button related methods know what type of action they should perform
        //this makes GUI very reusable, no point in adding additional buttons when you can use previous ones

        #endregion

        #region BatteryTypeTab variables

        private BitmapImage iconExpanded;
        private BitmapImage iconCollapsed;
        private GUIState batteryTypeTabState;
        private int selectedBatteryTypeId;
        private int selectedStationPricingId;
        private bool alreadySwapped;
        private BatteryType currentType;
        DataRowView currentInnerRow;

        #endregion

        #region AccountTab variables

        private EmployeeAccount currentAccount;
        private GUIState employeeAccountTabState;

        #endregion


        public MainWindow(EmployeeAccount currentAccount)
        {
            usedAccount = currentAccount;
            InitializeComponent();


            refreshTimer = new DispatcherTimer();
            refreshTimer.Tick += new EventHandler(dispatcherTimer_Tick);
            refreshTimer.Interval = new TimeSpan(0, 1, 0);
            refreshTimer.Start();



            //InitializeAdministratorWindow();
            if (usedAccount.employee_role == Role.Administrator)
            {
                InitializeAdministratorWindow();
            }
            else
            {
                InitializeEmployeeWindow();
            }

            
        }

        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            // Updating the Label which displays the current second
            RefreshAvailableBatteriesData(true);

            // Forcing the CommandManager to raise the RequerySuggested event
            CommandManager.InvalidateRequerySuggested();
        }

        private void InitializeAdministratorWindow()
        {
            try
            {
                System.Net.IPHostEntry e = System.Net.Dns.GetHostEntry("www.bing.com");
            }
            catch
            {
                mapView.Manager.Mode = AccessMode.CacheOnly;
                MessageBox.Show("No internet connection avaible, going to CacheOnly mode.", "", MessageBoxButton.OK, MessageBoxImage.Warning);
            }

            mapView.MapProvider = GMapProviders.BingMap;
            mapView.MinZoom = 3;
            mapView.MaxZoom = 20;
            mapView.Zoom = 7;
            mapView.ShowCenter = false; //do not show the center point of the cross
            mapView.DragButton = MouseButton.Left;
            mapView.Position = new PointLatLng(57.032817, 9.903800);

            RefreshAllData();
        }

        private void InitializeEmployeeWindow()
        {
            stationsTab.Visibility = Visibility.Hidden;
            batteryTypesTab.Visibility = Visibility.Hidden;
            accountTab.Visibility = Visibility.Hidden;
            RefreshEmployeeData();
        }

        private void RefreshAllData()
        {
            using (ManagementServiceClient client = new ManagementServiceClient())
            {
                InitializeStationTab(client.GetAllStations());
                InitializeBatteryTypeTab(client.GetAllBatteryTypes());
                InitializeEmployeeAccountTab(client.GetAllEmployeeAccounts());
                InitializeUserAccountTab(client.GetAllUserAccounts());
                allReservations = client.GetAllReservations().ToList();
                InitializeBatteryTabs();
            }
        }

        private void RefreshEmployeeData()
        {
            using (ManagementServiceClient client = new ManagementServiceClient())
            {
                usedAccount = client.ReloadAccount(usedAccount.session_token);
                allBatteryTypes = client.GetAllBatteryTypes();
                allUserAccounts = client.GetAllUserAccounts();
                allReservations = client.GetAllReservationsOnStation(usedAccount.Station);
                
            }
            if (allReservations == null)
            {
                LogOut();
            }
            else
            {
                allReservations = allReservations.ToList();
            }
            InitializeBatteryTabs();
        }

        private void RefreshVolatileData()
        {
            using (ManagementServiceClient client = new ManagementServiceClient())
            {
                InitializeStationTab(client.GetAllStations());
                InitializeBatteryTypeTab(client.GetAllBatteryTypes());
                //InitializeUserAccountTab(client.GetAllUserAccounts());
                InitializeEmployeeAccountTab(client.GetAllEmployeeAccounts());
            }
        }

        private void ReloadAvailableBatteriesData()
        {
            if(usedAccount.employee_role == Role.Administrator)
            {
                using(ManagementServiceClient client = new ManagementServiceClient())
                {
                    usedAccount = client.ReloadAccount(usedAccount.session_token);
                    DealWithExpiration(usedAccount != null);
                    InitializeStationTab(client.GetAllStations());
                    InitializeBatteryTypeTab(client.GetAllBatteryTypes());
                    InitializeUserAccountTab(client.GetAllUserAccounts());
                    allReservations = client.GetAllReservations().ToList();
                }
                InitializeBatteryTabs();
            }
            else
            {
                RefreshEmployeeData();
            }
        }

        private void RefreshEmployeeAccounts()
        {
            using (ManagementServiceClient client = new ManagementServiceClient())
            {
                InitializeEmployeeAccountTab(client.GetAllEmployeeAccounts());
            }
        }

        private void DealWithExpiration(bool sessionValid)
        {
            if(!sessionValid)
            {
                MessageBox.Show("Your session expired and the action will not be performed.\n"
                                + "You will now be logged out, to continue working please log in again.", "Session expired", MessageBoxButton.OK);
                LogOut();
            }
        }

        private void LogOut()
        {
            Login loginWindow = new Login();
                loginWindow.Show();
            this.Close();
        }

        private void OnLogOut_BtnClicked(object sender, RoutedEventArgs e)
        {
            LogOut();
        }

        #region Battery code

        private void InitializeBatteryTabs()
        {
            if(usedAccount.employee_role != Role.Administrator)
            {
                stationSelectionAvailableBatteriesComboBox.Visibility = Visibility.Hidden;
                stationSelectionAvailableBatteriesLbl.Visibility = Visibility.Hidden;

                stationSelectionReservedBatteriesComboBox.Visibility = Visibility.Hidden;
                stationSelectionReservedBatteriesLbl.Visibility = Visibility.Hidden;
            }

            InitializeReservedBatteryTab();
            InitializeAvaliableBatteriesTab();
        }




        #region Avalilable Batteries code

        private void InitializeAvaliableBatteriesTab()
        {
            availableBatteriesTabState = GUIState.VIEWING;
            batteryTypeSelectionComboBox.ItemsSource = allBatteryTypes.Select(b => b.name);
            if (usedAccount.employee_role == Role.Administrator)
            {
                stationSelectionAvailableBatteriesComboBox.ItemsSource = allStations.Select(s => s.name);
                stationSelectionAvailableBatteriesComboBox.SelectedIndex = -1;
                if (allStations.Count > 0)
                {
                    stationSelectionAvailableBatteriesComboBox.SelectedIndex = 0;
                }
            }
            else
            {
                RefreshAvailableBatteriesData(false);
            }
        }

        private void RefreshAvailableBatteriesData(bool retainSelection)
        {
            if (usedAccount.employee_role == Role.Administrator)
            {
                int selectedIndex = stationSelectionAvailableBatteriesComboBox.SelectedIndex;
                if (selectedIndex != -1)
                {
                    Station selectedStation = allStations[selectedIndex];
                    IEnumerable<int> batteryIds = selectedStation.Batteries.Select(b => b.id);
                    FillAvailableBatteryTable(allReservations.Where(r => batteryIds.Contains(r.battery_id)), selectedStation.Batteries, selectedStation, retainSelection);
                }

            }
            else
            {
                IEnumerable<int> batteryIds = usedAccount.Station.Batteries.Select(b => b.id);
                FillAvailableBatteryTable(allReservations, usedAccount.Station.Batteries, usedAccount.Station, retainSelection);
            }
        }

        private void FillAvailableBatteryTable(IEnumerable<BatteryReservation> reservations, IEnumerable<Battery> batteries, Station station, bool retainSelection)
        {
            int selected = -1;
            if(retainSelection)
            {
                selected = availableBattery_DataGrid.SelectedIndex;
            }
            DataTable mainTable = new DataTable();
            mainTable.Columns.Add("Battery Id", typeof(int));
            mainTable.Columns.Add("Time till charged", typeof(string));
            mainTable.Columns.Add("Battery type", typeof(string));
            mainTable.Columns.Add("Price for full", typeof(double));
            long nowTicks = DateTime.Now.Ticks;
            foreach(Battery bat in batteries)
            {
                BatteryType type;

                type = allBatteryTypes.Where(b => b.id == bat.battery_type_id).Single();

                if(reservations.Where(r => Math.Abs(r.time_of_reservation.Ticks - nowTicks) < (10000 * 1000 * 60 * (long)type.average_charging_time)).Count() == 0)
                {
                    double price = station.Pricings.Where(p => p.battery_type_id == type.id).Single().price;
                    mainTable.Rows.Add(bat.id, HourFormString((int)((bat.charge_time.Value.Ticks - nowTicks) / 10000 / 1000 / 60)), type.name, price);
                }
            }
            availableBattery_DataGrid.DataContext = mainTable;
            availableBattery_DataGrid.SelectedIndex = selected;
        }

        private void SaveNewBattery()
        {
            int selectedIndex = batteryTypeSelectionComboBox.SelectedIndex;
            if(selectedIndex != -1)
            {
                Battery bat = new Battery() { battery_type_id = allBatteryTypes[selectedIndex].id, charge_time = DateTime.Now };
                if(usedAccount.employee_role == Role.Administrator)
                {
                    bat.station_id = allStations[stationSelectionAvailableBatteriesComboBox.SelectedIndex].id;
                }
                else
                {
                    bat.station_id = (int) usedAccount.station_id;
                }

                using(ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.AddNewBattery(bat, usedAccount.session_token));
                }
                SwitchToAvailableBatteryViewing();
                ReloadAvailableBatteriesData();
            }
        }

        private void DeleteBattery()
        {
            DataRowView row = (DataRowView) availableBattery_DataGrid.SelectedItem;
            if(row != null)
            {
                Battery bat = new Battery() { id = (int)row[0] };
                using (ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.DeleteBattery(bat, usedAccount.session_token));
                }
                ReloadAvailableBatteriesData();
            }
        }

        private void SwitchToAvailableBatteryViewing()
        {
            availableBatteriesTabState = GUIState.VIEWING;
            batteryTypeSelectionComboBox.IsEnabled = false;
            batteryTypeSelectionComboBox.SelectedItem = null;
            addNewBatteryBtn.Content = "Add New Battery";
            deleteBatteryBtn.Content = "Delete Battery";
        }

        private void AddNewBattery_BtnClicked(object sender, RoutedEventArgs e)
        {
            if(availableBatteriesTabState == GUIState.VIEWING)
            {
                availableBatteriesTabState = GUIState.ADDING;
                batteryTypeSelectionComboBox.IsEnabled = true;
                addNewBatteryBtn.Content = "Save New Battery";
                deleteBatteryBtn.Content = "Cancel";
            }
            else if(availableBatteriesTabState == GUIState.ADDING)
            {
                SaveNewBattery();
            }
           

        }

        private void DeleteBattery_BtnClicked(object sender, RoutedEventArgs e)
        {
            if(availableBatteriesTabState == GUIState.ADDING)
            {
                SwitchToAvailableBatteryViewing();
            }
            else
            {
                DeleteBattery();
            }
        }

        private void OnStationSelectionChangedAvailableBattery(object sender, SelectionChangedEventArgs e)
        {
            RefreshAvailableBatteriesData(false);
        }

        #endregion

        #region Reserved Batteries code

        private void InitializeReservedBatteryTab()
        {
            if (usedAccount.employee_role == Role.Administrator)
            {
                stationSelectionReservedBatteriesComboBox.ItemsSource = allStations.Select(s => s.name);
                if (allStations.Count > 0)
                {
                    stationSelectionReservedBatteriesComboBox.SelectedIndex = 0;
                }
            }
            else
            {
                RefreshReservedBatteryData();
            }
        }
        private void RefreshReservedBatteryData()
        {
            if (usedAccount.employee_role == Role.Administrator)
            {
                int selectedIndex = stationSelectionReservedBatteriesComboBox.SelectedIndex;
                if(selectedIndex != -1)
                {
                    Station selectedStation = allStations[selectedIndex];
                    IEnumerable<int> batteryIds = selectedStation.Batteries.Select(b => b.id);
                    FillReservedBatteryTable(allReservations.Where(r => batteryIds.Contains(r.battery_id)), selectedStation.Batteries, selectedStation);
                }

            }
            else
            {
                IEnumerable<int> batteryIds = usedAccount.Station.Batteries.Select(b => b.id);
                FillReservedBatteryTable(allReservations, usedAccount.Station.Batteries, usedAccount.Station);
            }
        }

        private void FillReservedBatteryTable(IEnumerable<BatteryReservation> pickedReservations, IEnumerable<Battery> stationBatteries, Station station)
        {
            Log("All reservations count => " + allReservations.Count);
            DataTable mainTable = new DataTable();
            mainTable.Columns.Add("Reservation Id", typeof(int));
            mainTable.Columns.Add("Customer Id", typeof(int));
            mainTable.Columns.Add("BatteryType price", typeof(double));
            mainTable.Columns.Add("Customer Name", typeof(string));
            mainTable.Columns.Add("Reservation Time", typeof(DateTime));
            mainTable.Columns.Add("Battery Type", typeof(string));

            foreach(BatteryReservation reservation in pickedReservations)
            {
                Log("All route reservatins count => " + (allUserAccounts.SelectMany(a => a.RouteReservations).Count()));
                UserAccount searchedUser = allUserAccounts.Where(a => a.RouteReservations.Select(r => r.id).Contains((int) reservation.route_reservation_id)).Single();
                BatteryType type;

                type = allBatteryTypes.Where(b => b.id == stationBatteries.Where(bat => bat.id == reservation.battery_id).Single().battery_type_id).Single();

                double price = station.Pricings.Where(p => p.battery_type_id == type.id).Single().price;
                mainTable.Rows.Add(reservation.id, searchedUser.id, price, searchedUser.fname + " " + searchedUser.lname, reservation.time_of_reservation, type.name);

            }
            reservedBattery_DataGrid.DataContext = mainTable;

            if(reservedBattery_DataGrid.Columns.Count > 3)
            {
                reservedBattery_DataGrid.Columns[0].Visibility = Visibility.Hidden;
                reservedBattery_DataGrid.Columns[1].Visibility = Visibility.Hidden;
                reservedBattery_DataGrid.Columns[2].Visibility = Visibility.Hidden;
            }
        }

        private void OnRowSelectionChangedReservedBattery(object sender, SelectionChangedEventArgs e)
        {
            DataGrid grid = (DataGrid)sender;
            if (grid.SelectedItem != null)
            {
                DataRowView row = (DataRowView)grid.SelectedItem;

                resIdtxtBox.Text = row[0].ToString();
                custIdTxtBox.Text = row[1].ToString();
                custNameTxtBox.Text = row[3].ToString();
                resTimeTxtBox.Text = row[4].ToString();
                resBatTypeTxtBox.Text = row[5].ToString();
            }
            else
            {
                custNameTxtBox.Text = "";
                custIdTxtBox.Text = "";
                resIdtxtBox.Text = "";
                resTimeTxtBox.Text = "";
                resBatTypeTxtBox.Text = "";
            }
        }

        private void OnReservedBatteryTableLoaded(object sender, RoutedEventArgs e)
        {
            if (reservedBattery_DataGrid.Columns.Count > 3)
            {
                reservedBattery_DataGrid.Columns[0].Visibility = Visibility.Hidden;
                reservedBattery_DataGrid.Columns[1].Visibility = Visibility.Hidden;
                reservedBattery_DataGrid.Columns[2].Visibility = Visibility.Hidden;
            }
        }

        private Battery GetReservationBattery(BatteryReservation reservation)
        {
            if(usedAccount.employee_role == Role.Administrator)
            {
                return allStations[stationSelectionReservedBatteriesComboBox.SelectedIndex].Batteries.Where(b => b.id == reservation.battery_id).Single();
            }
            else
            {
                return usedAccount.Station.Batteries.Where(b => b.id == reservation.battery_id).Single();
            }
        }

        private BatteryType GetReservationBatteryType(Battery battery)
        {
            if (usedAccount.employee_role == Role.Administrator)
            {
                return allBatteryTypes.Where(bt => bt.id == battery.battery_type_id).Single();
            }
            else
            {
                return battery.BatteryType;
            }
        }

        private bool SaveExchange()
        {
            string percCharge = percChargeLeftReservedBatteryTxtBox.Text;
            double charge = 0;
            if (double.TryParse(percCharge, out charge) && charge <= 100 && charge >= 0)
            {
                
                BatteryReservation reservation = allReservations.Where(r => r.id == int.Parse(resIdtxtBox.Text)).Single();
                reservation.completed = true;
                reservation.estimated_usage = 100 - charge;
                Battery respectiveBattery = GetReservationBattery(reservation);
                BatteryType type = GetReservationBatteryType(respectiveBattery);
                respectiveBattery.charge_time = new DateTime(DateTime.Now.Ticks + ((long)type.average_charging_time * (long)reservation.estimated_usage * 1000 * 100 * 60));
                using(ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.UpdateReservation(reservation, usedAccount.session_token));
                    DealWithExpiration(client.UpdateBattery(respectiveBattery, usedAccount.session_token));
                }
                allReservations.Remove(reservation);
                RefreshReservedBatteryData();
                return true;
            }
            else
            {
                MessageBox.Show("The charge percentage must be a number between 0 and 100");
                return false;
            }
        }

        private void OnCancelBatteryExchange_BtnClicked(object sender, RoutedEventArgs e)
        {
            FinishExchange();
        }

        private void OnExchangeBattery_BtnClicked(object sender, RoutedEventArgs e)
        {
            if(cancelExchangeBattery_Btn.Visibility == Visibility.Hidden)  //lame hack, but I don't have time to make it better
            {
                percChargeLeftReservedBatteryTxtBox.Text = "";
                percChargeLeftReservedBatteryLbl.Visibility = Visibility.Visible;
                percChargeLeftReservedBatteryTxtBox.Visibility = Visibility.Visible;
                totalPriceReservedBatteryLbl.Visibility = Visibility.Visible;
                totalPriceReservedBatteryTxtBox.Visibility = Visibility.Visible;
                cancelExchangeBattery_Btn.Visibility = Visibility.Visible;
                exchangeBatteryBtn.Content = "Confirm Exchange";
            }
            else
            {
                if(SaveExchange())
                {
                    FinishExchange();
                }
            }
        }

        private void FinishExchange()
        {
            percChargeLeftReservedBatteryLbl.Visibility = Visibility.Hidden;
            percChargeLeftReservedBatteryTxtBox.Visibility = Visibility.Hidden;
            totalPriceReservedBatteryLbl.Visibility = Visibility.Hidden;
            totalPriceReservedBatteryTxtBox.Visibility = Visibility.Hidden;
            cancelExchangeBattery_Btn.Visibility = Visibility.Hidden;
            reservedBattery_DataGrid.IsEnabled = true;
        }

        private void OnPercChargeBatteryResChanged(object sender, TextChangedEventArgs e)
        {
            double percCharge = 0;
            string perc = percChargeLeftReservedBatteryTxtBox.Text;
            if(perc == "")
            {
                totalPriceReservedBatteryTxtBox.Text = "";
            }
            else if(double.TryParse(perc, out percCharge) && percCharge >= 0 && percCharge <= 100)
            {
                lastWorkingPercentage = percCharge;
                DataRowView row = (DataRowView) reservedBattery_DataGrid.SelectedItem;
                if (row != null)
                {
                    double priceForFull = (double) row[2];
                    totalPriceReservedBatteryTxtBox.Text = ((int)((100 - percCharge) / 100 * priceForFull)).ToString();
                }
            }
            else
            {
                percChargeLeftReservedBatteryTxtBox.Text = lastWorkingPercentage.ToString();
                percChargeLeftReservedBatteryTxtBox.CaretIndex = percChargeLeftReservedBatteryTxtBox.Text.Length;
            }

        }

        private void OnStationSelectionChangedReservedBatteries(object sender, SelectionChangedEventArgs e)
        {
            RefreshReservedBatteryData();
        }

        private void OnBatterySearched(object sender, TextChangedEventArgs e)
        {
            string searchedName = batteryReservationSearchBox.Text.ToLower();
            if(searchedName == "")
            {
                reservedBattery_DataGrid.SelectedItem = null;
            }
            else
            {
                foreach(DataRowView row in reservedBattery_DataGrid.Items)
            {
                if((row[3] as string).ToLower().StartsWith(searchedName))
                {
                    reservedBattery_DataGrid.SelectedItem = row;
                    break;
                }
            }
            }
            
        }


        #endregion

        #endregion


        #region Station tab code

        private void InitializeStationTab(IList<Station> allStations)
        {
            this.allStations = allStations;
            stationTabState = GUIState.VIEWING;
            mapView.Markers.Clear();
            

            foreach (Station st in allStations)
            {
                double lat = st.latitude;
                double lng = st.longitude;
                GMapMarker marker = new GMapMarker(new PointLatLng(lat, lng));
                marker.Shape = new StationMarker(this, marker, st.name) { StationId = st.id };

                mapView.Markers.Add(marker);
                allMarkers.Add(marker);
            }
        }


        private void AddNewStationBtn_Click(object sender, RoutedEventArgs e)
        {
            switch(stationTabState)
            {
                case GUIState.ADDING:
                    SaveNewStation();
                    break;
                case GUIState.EDITING:
                    SaveStationChanges();
                    break;
                case GUIState.VIEWING:
                    SwitchToStationGUIState(GUIState.ADDING);
                    break;
                default:
                    break;
            }
        }

        private void DeleteStation_BtnClicked(object sender, RoutedEventArgs e)
        {
            switch (stationTabState)
            {
                case GUIState.ADDING:
                    CancelStationAdding();
                    break;
                case GUIState.EDITING:
                    DeleteStation();
                    break;
                case GUIState.VIEWING:
                    break;
                default:
                    break;
            }
        }

        private void SaveNewStation()
        {
            if(markerName != "")
            {
                if(currentMarker.Shape != null)
                {
                    PointLatLng point = currentMarker.Position;
                    Station newStation = new Station() { latitude = point.Lat, longitude = point.Lng, name = markerName };
                    using (ManagementServiceClient client = new ManagementServiceClient())
                    {
                        DealWithExpiration(client.AddStation(newStation, usedAccount.session_token));
                    }
                    SwitchToStationGUIState(GUIState.VIEWING);
                    RefreshVolatileData();
                }
                else
                {
                    MessageBox.Show(this, "You have to add station to the map!");
                }
            }
            else
            {
                MessageBox.Show(this, "You have to name the station!");
            }
        }

        private void SaveStationChanges()
        {
            if(markerName != "")
            {
                using (ManagementServiceClient client = new ManagementServiceClient())
                {
                    PointLatLng point = currentMarker.Position;
                    StationMarker markerShape = (StationMarker) currentMarker.Shape;
                    Station station = new Station() { id = markerShape.StationId, latitude = point.Lat, longitude = point.Lng, name = markerName };
                    DealWithExpiration(client.UpdateStation(station, usedAccount.session_token));

                    markerShape.IsSelected = false;
                    currentMarker = null;
                    SwitchToStationGUIState(GUIState.VIEWING);
                }
            }
            else
            {
                MessageBox.Show(this, "You have to name the station!");
            }
        }

        private void CancelStationAdding()
        {
            currentMarker.Clear();
            mapView.Markers.Remove(currentMarker);
            currentMarker = null;
            SwitchToStationGUIState(GUIState.VIEWING);
        }

        private void CancelStationEditing()
        {
            (currentMarker.Shape as StationMarker).Title = originalName;
            (currentMarker.Shape as StationMarker).IsSelected = false;
            originalName = null;
            currentMarker = null;
            markerName = null;
            SwitchToStationGUIState(GUIState.VIEWING);
        }

        private void DeleteStation()
        {
            Log("Deleteing station");
            if(currentMarker != null)
            {
                using (ManagementServiceClient client = new ManagementServiceClient())
                {
                    Station station = new Station() { id = (currentMarker.Shape as StationMarker).StationId };
                    DealWithExpiration(client.RemoveStation(station, usedAccount.session_token));
                }
                currentMarker.Clear();
                mapView.Markers.Remove(currentMarker);
                allMarkers.Remove(currentMarker);
                currentMarker = null;
                markerName = "";
                originalName = null;
                RefreshVolatileData();
                SwitchToStationGUIState(GUIState.VIEWING);
            }
        }

        private void SwitchToStationGUIState(GUIState state)
        {
            stationTabState = state;
            switch(state)
            {
                case GUIState.ADDING:
                    SwitchToStationAdding();
                    break;
                case GUIState.EDITING:
                    SwitchToStationEditing();
                    break;
                case GUIState.VIEWING:
                    SwitchToStationViewing();
                    break;
                default:
                    break;
            }
            
        }

        private void SwitchToStationAdding()
        {
            currentMarker = new GMapMarker();
            markerName = "";

            stNameTxtBox.IsReadOnly = false;

            addNewStation_Btn.Content = "Save Station";
            deleteStation_Btn.Content = "Cancel";

            deleteStation_Btn.Visibility = System.Windows.Visibility.Visible;
            selectStationLbl.Visibility = Visibility.Visible;

            searchStationLbl.Visibility = Visibility.Hidden;
            searchStationTxtBox.Visibility = Visibility.Hidden;

        }

        private void SwitchToStationEditing()
        {
            StationMarker shape = (StationMarker) currentMarker.Shape;
            shape.IsSelected = true;
            originalName = shape.Title;
            markerName = originalName;
            stNameTxtBox.Text = markerName;
            stNameTxtBox.IsReadOnly = false;
            

            addNewStation_Btn.Content = "Edit Station";
            deleteStation_Btn.Content = "Delete";

            searchStationLbl.Visibility = Visibility.Visible;
            searchStationTxtBox.Visibility = Visibility.Visible;
            deleteStation_Btn.Visibility = Visibility.Visible;

            selectStationLbl.Visibility = Visibility.Hidden;
        }

        private void SwitchToStationViewing()
        {
            stNameTxtBox.IsReadOnly = true;
            stNameTxtBox.Clear();
            markerName = "";

            addNewStation_Btn.Content = "Add Station";
            deleteStation_Btn.Visibility = Visibility.Hidden;
            selectStationLbl.Visibility = Visibility.Hidden;

            addNewStation_Btn.Visibility = Visibility.Visible;
            searchStationLbl.Visibility = Visibility.Visible;
            searchStationTxtBox.Visibility = Visibility.Visible;
        }

        private void OnPreviewMouseLeftButtonDownMapView(object sender, MouseButtonEventArgs e)
        {
            if (stationTabState == GUIState.ADDING)
            {
                draggingStation = IsMarkerClicked(currentMarker);
                Debug.WriteLine("Intersects worked => " + draggingStation);

                mapView.CanDragMap = !draggingStation;
            }
            else if(!IsMarkerClicked(currentMarker))
            {
                if (stationTabState == GUIState.EDITING)
                {
                    CancelStationEditing();
                }
                foreach(GMapMarker marker in allMarkers)
                {
                    if(IsMarkerClicked(marker))
                    {
                        currentMarker = marker;
                        //searchStationTxtBox.Text = (marker.Shape as StationMarker).Title;
                        SwitchToStationGUIState(GUIState.EDITING);
                        break;
                    }
                }
            }
        }

        private void OnMouseLeftButtonDownMapView(object sender, MouseButtonEventArgs e)
        {
            String content2 = "Move the station point by draging it on the map.";
            Debug.WriteLine("OnMouseLeftButtonDown");
            if (currentMarker != null && currentMarker.Map == null)
            {
                System.Windows.Point clickPoint = e.GetPosition(mapView);
                PointLatLng point = mapView.FromLocalToLatLng((int)clickPoint.X, (int)clickPoint.Y);

                currentMarker.Position = point;
                currentMarker.Shape = new StationMarker(this, currentMarker, markerName) { IsDraggable = true, IsSelected = true };
                mapView.Markers.Add(currentMarker);
                selectStationLbl.Content = content2;
            }
        }

        private void OnMouseLeftButtonUpMapView(object sender, MouseButtonEventArgs e)
        {
            draggingStation = false;
            mapView.CanDragMap = true;
        }

        private void OnMouseDoubleClickMapView(object sender, MouseButtonEventArgs e)
        {
            if(currentMarker != null)
            {
                Log("Double clicked");
            }
        }

        private bool IsMarkerClicked(GMapMarker marker)
        {
            if(marker == null || marker.Shape == null)
            {
                return false;
            }
            return marker.Shape.IsMouseOver;
        }

        private void Log(string text)
        {
            Debug.WriteLine(text);
        }

        private void OnStationNameSet(object sender, TextChangedEventArgs e)
        {
            markerName = (sender as TextBox).Text;
            if(currentMarker != null && currentMarker.Shape != null)
            {
                (currentMarker.Shape as StationMarker).Title = markerName;
            }
        }

        //private void OnMarkerSelected(GMapMarker marker)
        //{
        //    StationMarker markerShape = (StationMarker)marker.Shape;
        //    markerName = markerShape.Title;
        //}

        private void OnStationSearchTextChanged(object sender, TextChangedEventArgs e)
        {
            string searchText = (sender as TextBox).Text;
            foreach (GMapMarker marker in allMarkers)
            {
                if (searchText == "")
                {
                    if (currentMarker != null && marker != currentMarker)
                    {
                        CancelStationEditing();
                    }
                    return;
                }
                else if ((marker.Shape as StationMarker).Title.ToLower().StartsWith(searchText.ToLower()))
                {
                    if (currentMarker != null && marker != currentMarker)
                    {
                        CancelStationEditing();
                    }
                    currentMarker = marker;
                    mapView.Position = currentMarker.Position;
                    SwitchToStationGUIState(GUIState.EDITING);

                    return;
                }
            }
            if (currentMarker != null)
            {
                CancelStationEditing();
            }
            return;
        }

        #endregion

        #region Battery tab code

        private void InitializeBatteryTypeTab(IList<BatteryType> allTypes)
        {
            selectedBatteryTypeId = -1;
            selectedStationPricingId = -1;
            allBatteryTypes = allTypes;
            iconCollapsed = new BitmapImage(new Uri(@"Resources\toggle_collapse_blue.png", UriKind.Relative));
            iconExpanded = new BitmapImage(new Uri(@"Resources\toggle_expand_blue.png", UriKind.Relative));
            ResetBatteryTypeTable();
            //BatteryType_DataGrid.Columns[0].Visibility = System.Windows.Visibility.Hidden;
            this.BatteryType_DataGrid.RowDetailsVisibilityChanged += new EventHandler<DataGridRowDetailsEventArgs>(BatteryType_DataGrid_RowDetailsVisibilityChanged);
        }

        void BatteryType_DataGrid_RowDetailsVisibilityChanged(object sender, DataGridRowDetailsEventArgs e)
        {
            Log(sender.GetType().ToString());
            
            DataRowView rowView = (DataRowView)e.Row.Item;
            Log("Id => " + rowView[0]);
            int type_id = (int)rowView[0];
            DataTable inner = new DataTable();
            inner.Columns.Add("Pricing id", typeof(int));
            inner.Columns.Add("Station id", typeof(int));
            inner.Columns.Add("Station name", typeof(string));
            inner.Columns.Add("Price", typeof(double));

            foreach (Station station in allStations)
            {
                Pricing pricing = station.Pricings.Where(p => p.battery_type_id == type_id).SingleOrDefault();
                if (pricing != null)
                {
                    inner.Rows.Add(pricing.id, station.id, station.name, pricing.price);
                }
            }
            DataGrid innerGrid = e.DetailsElement as DataGrid;
            innerGrid.ItemsSource = (inner as IListSource).GetList();
            innerGrid.Columns[0].Visibility = Visibility.Hidden;
            innerGrid.Columns[1].Visibility = Visibility.Hidden;
        }

        private void ExpandCollapseDetailsGridView(object sender, RoutedEventArgs e)
        {
            try
            {
                DataGridRow row = GetSelectedRow(BatteryType_DataGrid);
                if(row.DetailsVisibility == Visibility.Collapsed)
                {
                    row.DetailsVisibility = Visibility.Visible;
                }
                else
                {
                    row.DetailsVisibility = Visibility.Collapsed;
                }
            }
            catch (System.Exception)
            {
            }
        }

        private void OnOuterGridLoaded(object sender, RoutedEventArgs e)
        {
            if (BatteryType_DataGrid.Columns.Count > 1)
            {
                BatteryType_DataGrid.Columns[1].Visibility = System.Windows.Visibility.Hidden;
            }
        }

        private void OnSelectionChangedOuterGrid(object sender, SelectionChangedEventArgs e)
        {
            DataGrid dg = (DataGrid)sender;

            if (dg.SelectedItem != null)
            {
                int batTypeId = int.Parse((dg.SelectedItem as DataRowView)[0].ToString());
                if (batTypeId != selectedBatteryTypeId)
                {
                    if(selectedBatteryTypeId == -1)
                    {
                        SwitchToBatteryTypeGUIState(GUIState.VIEWING);
                    }
                    else if (batteryTypeTabState == GUIState.EDITING)
                    {
                        CancelBatteryTypeEditing();
                    }
                    FillBatteryTypeBoxes(batTypeId);
                    if (!alreadySwapped)
                    {
                        FillPricingBoxes(-1);
                    }
                    else
                    {
                        FillPricingBoxes(selectedStationPricingId);
                        alreadySwapped = false;
                    }
                }
            }
        }

        private void OnSelectionChangedInnerGrid(object sender, SelectionChangedEventArgs e)
        {
            DataGrid dg = (DataGrid)sender;
            if (dg.SelectedItem != null)
            {
                currentInnerRow = (DataRowView) dg.SelectedItem;
                FillPricingBoxes(int.Parse((dg.SelectedItem as DataRowView)[1].ToString()));
                dg.SelectedItem = null;
            }
        }

        private void FillBatteryTypeBoxes(int batteryTypeId)
        {
            selectedBatteryTypeId = -1;
            if (batteryTypeId == -1)
            {
                batteryTypeNameTxtBox.IsEnabled = false;
                batteryTypeNameTxtBox.Text = "";
                maximumTravelDistanceTxtBox.IsEnabled = false;
                maximumTravelDistanceTxtBox.Text = "";
                averageChargingTimeTxtBox.IsEnabled = false;
                averageChargingTimeTxtBox.Text = "";
            }
            else if(batteryTypeId == - 2)
            {
                batteryTypeNameTxtBox.IsEnabled = true;
                batteryTypeNameTxtBox.Text = "";
                maximumTravelDistanceTxtBox.IsEnabled = true;
                maximumTravelDistanceTxtBox.Text = "";
                averageChargingTimeTxtBox.IsEnabled = true;
                averageChargingTimeTxtBox.Text = "";
            }
            else
            {
                BatteryType type = allBatteryTypes.Where(bt => bt.id == batteryTypeId).Single();
                batteryTypeNameTxtBox.IsEnabled = true;
                batteryTypeNameTxtBox.Text = type.name;

                maximumTravelDistanceTxtBox.IsEnabled = true;
                maximumTravelDistanceTxtBox.Text = type.maximum_distance.ToString();

                averageChargingTimeTxtBox.IsEnabled = true;
                averageChargingTimeTxtBox.Text = type.average_charging_time.ToString();
            }
            selectedBatteryTypeId = batteryTypeId;
        }

        private void FillPricingBoxes(int stationId)
        {
            Log("Battery type id => " + selectedBatteryTypeId);
            Log("Station id => " + stationId);
            selectedStationPricingId = -1;
            if (stationId != -1 && selectedBatteryTypeId != -1)
            {
                alreadySwapped = true;
                priceBatteryTypeTxtBox.IsEnabled = true;
                Station station = allStations.Where(s => s.id == stationId).Single();
                stationNamePricingTxtBox.Text = station.name;
                BatteryType type = GUIState.EDITING == batteryTypeTabState ? 
                    currentType : allBatteryTypes.Where(bt => bt.id == selectedBatteryTypeId).Single();

                priceBatteryTypeTxtBox.Text = type.Pricings.Where(p => p.station_id == station.id).Single().price.ToString();
                selectedStationPricingId = stationId;
            }
            else
            {
                priceBatteryTypeTxtBox.IsEnabled = false;
                stationNamePricingTxtBox.Text = "";
                priceBatteryTypeTxtBox.Text = "";
            }
        }


        private void SaveBatteryChanges_BtnClicked(object sender, RoutedEventArgs e)
        {
            switch(batteryTypeTabState)
            {
                case GUIState.ADDING:
                    SaveNewBatteryType();
                    break;
                case GUIState.EDITING:
                    UpdateBatteryType();
                    break;
                default:
                    break;
            }
        }

        private void AddBatteryType_BtnClicked(object sender, RoutedEventArgs e)
        {
            SwitchToBatteryTypeGUIState(GUIState.ADDING);
        }

        private void DeleteBatteryType_BtnClicked(object sender, RoutedEventArgs e)
        {
            switch(batteryTypeTabState)
            {
                case GUIState.ADDING:
                    CancelBatteryTypeAdding();
                    break;
                case GUIState.EDITING:
                    CancelBatteryTypeEditing();
                    break;
                case GUIState.VIEWING:
                    DeleteBatteryType();
                    break;
                default:
                    break;
            }
        }


        private void SwitchToBatteryTypeGUIState(GUIState state)
        {
            batteryTypeTabState = state;
            switch(state)
            {
                case GUIState.ADDING:
                    SwitchToBatteryTypeAdding();
                    break;
                case GUIState.EDITING:
                    SwitchToBatteryTypeEditing();
                    break;
                case GUIState.VIEWING:
                    SwitchToBatteryTypeViewing();
                    break;
                default:
                    break;
            }
        }

        

        private void SwitchToBatteryTypeAdding()
        {
            FillBatteryTypeBoxes(-2);
            FillPricingBoxes(-1);

            BatteryType_DataGrid.IsEnabled = false;
            saveBatteryChanges_Btn.IsEnabled = true;
            saveBatteryChanges_Btn.Content = "Save New Type";
            addNewBatteryType_Btn.Visibility = Visibility.Hidden;
            deleteBatteryType_Btn.IsEnabled = true;
            deleteBatteryType_Btn.Content = "Cancel";

            currentType = new BatteryType();
        }

        private void SwitchToBatteryTypeEditing()
        {
            BatteryType_DataGrid.IsEnabled = true;
            addNewBatteryType_Btn.Visibility = Visibility.Hidden;
            saveBatteryChanges_Btn.IsEnabled = true;
            deleteBatteryType_Btn.IsEnabled = true;
            saveBatteryChanges_Btn.Content = "Save Changes";
            deleteBatteryType_Btn.Content = "Cancel Changes";
            BatteryType selectedType = allBatteryTypes.Where(bt => bt.id == selectedBatteryTypeId).Single();
            currentType = new BatteryType()
            {
                id = selectedType.id,
                name = selectedType.name,
                average_charging_time = selectedType.average_charging_time,
                maximum_distance = selectedType.maximum_distance,
                Pricings = selectedType.Pricings.Select(
                p => new Pricing 
                {  
                    id = p.id, 
                    price = p.price, 
                    station_id = p.station_id,
                    battery_type_id = p.battery_type_id 
                }).ToArray()
            };
        }

        private void SwitchToBatteryTypeViewing()
        {
            BatteryType_DataGrid.IsEnabled = true;
            addNewBatteryType_Btn.Visibility = Visibility.Visible;
            saveBatteryChanges_Btn.IsEnabled = false;
            deleteBatteryType_Btn.IsEnabled = true;
            saveBatteryChanges_Btn.Content = "Save Changes";
            deleteBatteryType_Btn.Content = "Delete Type";
        }

        private bool CheckTypeDataCorrectness()
        {
            if (batteryTypeNameTxtBox.Text == "" || averageChargingTimeTxtBox.Text == "" || maximumTravelDistanceTxtBox.Text == "")
            {
                MessageBox.Show("You have to fill all battery type data!");
                return false;
            }
            string chargeTime = averageChargingTimeTxtBox.Text;
            string distance = maximumTravelDistanceTxtBox.Text;
            int i;
            if(!int.TryParse(chargeTime, out i))
            {
                MessageBox.Show("Time must be a number!");
                return false;
            }

            if(!int.TryParse(distance, out i))
            {
                MessageBox.Show("Distance must be a number!");
                return false;
            }

            return true;
        }

        private void SaveNewBatteryType()
        {
            if(CheckTypeDataCorrectness())
            {
                using (ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.AddNewBatteryType(currentType, usedAccount.session_token));
                }
                RefreshVolatileData();
                SwitchToBatteryTypeGUIState(GUIState.VIEWING);
            }
        }

        private void UpdateBatteryType()
        {
            if (CheckTypeDataCorrectness())
            {
                using (ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.UpdateBatteryType(currentType, usedAccount.session_token));
                }
                foreach(Pricing p in currentType.Pricings)
                {
                    Log("Pricing price => " + p.price + " id => " + p.id);
                }
                RefreshVolatileData();
                SwitchToBatteryTypeGUIState(GUIState.VIEWING);
            }
        }

        private void DeleteBatteryType()
        {
            if(selectedBatteryTypeId != -1)
            {
                BatteryType bt = new BatteryType() { id = selectedBatteryTypeId } ;
                using (ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.DeleteBatteryType(bt, usedAccount.session_token));
                }
                RefreshVolatileData();
                SwitchToBatteryTypeGUIState(GUIState.VIEWING);
            }
            
        }

        private void CancelBatteryTypeAdding()
        {
            ResetBatteryTypeTable();
            SwitchToBatteryTypeGUIState(GUIState.VIEWING);
        }

        private void CancelBatteryTypeEditing()
        {
            ResetBatteryTypeTable();
            SwitchToBatteryTypeGUIState(GUIState.VIEWING);
        }


        private void ResetBatteryTypeTable()
        {
            currentType = null;
            selectedBatteryTypeId = -1;
            selectedStationPricingId = -1;
            DataTable mainBatteryTypeTable = new DataTable();
            mainBatteryTypeTable.Columns.Add("Id", typeof(int));
            mainBatteryTypeTable.Columns.Add("Name", typeof(string));
            mainBatteryTypeTable.Columns.Add("Charging time", typeof(string));
            mainBatteryTypeTable.Columns.Add("Maximum travel distance", typeof(int));

            foreach (BatteryType type in allBatteryTypes)
            {
                int hours = type.average_charging_time / 60;
                int minutes = type.average_charging_time % 60;
                string time = String.Format("{0} h, {1} m", hours, minutes);
                mainBatteryTypeTable.Rows.Add(type.id, type.name, time, type.maximum_distance);
            }

            batteryTypeNameTxtBox.Text = "";
            batteryTypeNameTxtBox.IsEnabled = false;
            averageChargingTimeTxtBox.Text = "";
            averageChargingTimeTxtBox.IsEnabled = false;
            maximumTravelDistanceTxtBox.Text = "";
            maximumTravelDistanceTxtBox.IsEnabled = false;
            stationNamePricingTxtBox.Text = "";
            stationNamePricingTxtBox.IsEnabled = false;
            priceBatteryTypeTxtBox.Text = "";
            priceBatteryTypeTxtBox.IsEnabled = false;

            BatteryType_DataGrid.DataContext = mainBatteryTypeTable;

            if (BatteryType_DataGrid.Columns.Count > 1)
            {
                BatteryType_DataGrid.Columns[1].Visibility = System.Windows.Visibility.Hidden;
            }
        }

        private void TrytoStartEditing()
        {
            if(batteryTypeTabState == GUIState.VIEWING)
            {
                SwitchToBatteryTypeGUIState(GUIState.EDITING);
                
            }
        }

        private void OnBatteryTypeNameTextChanged(object sender, TextChangedEventArgs e)
        {
            if (selectedBatteryTypeId != -1)
            {
                TrytoStartEditing();
                currentType.name = batteryTypeNameTxtBox.Text;
                if (selectedBatteryTypeId != -2)
                {
                    (BatteryType_DataGrid.SelectedItem as DataRowView)[1] = currentType.name;
                }
                
            }
        }

        private void OnAverageChargeTimeChanged(object sender, TextChangedEventArgs e)
        {
            if (selectedBatteryTypeId != -1)
            {
                TrytoStartEditing();
                string chargeTime = averageChargingTimeTxtBox.Text;
                int averageChargeTime = 0;
                if (int.TryParse(chargeTime, out averageChargeTime))
                {
                    currentType.average_charging_time = averageChargeTime;
                    if (selectedBatteryTypeId != -2)
                    {
                        (BatteryType_DataGrid.SelectedItem as DataRowView)[2] = HourFormString(averageChargeTime);
                    }

                }
                else if (chargeTime == "")
                {
                    currentType.average_charging_time = 0;
                    if (selectedBatteryTypeId != -2)
                    {
                        (BatteryType_DataGrid.SelectedItem as DataRowView)[2] = HourFormString(0);
                    }

                }
                else
                {
                    averageChargingTimeTxtBox.Text = currentType.average_charging_time != 0 ? currentType.average_charging_time.ToString() : "";
                    averageChargingTimeTxtBox.CaretIndex = averageChargingTimeTxtBox.Text.Length;
                }
            }
        }

        private void OnMaximumTravelDistanceChanged(object sender, TextChangedEventArgs e)
        {
            if (selectedBatteryTypeId != -1)
            {
                TrytoStartEditing();
                string distance = maximumTravelDistanceTxtBox.Text;
                int maximumDistance = 0;
                if (int.TryParse(distance, out maximumDistance))
                {
                    currentType.maximum_distance = maximumDistance;
                    if(selectedBatteryTypeId != -2)
                    {
                        (BatteryType_DataGrid.SelectedItem as DataRowView)[3] = maximumDistance;
                    }
                }
                else if (distance == "")
                {
                    currentType.maximum_distance = 0;
                    if (selectedBatteryTypeId != -2)
                    {
                        (BatteryType_DataGrid.SelectedItem as DataRowView)[3] = 0;
                    }
                }
                else
                {
                    maximumTravelDistanceTxtBox.Text = currentType.maximum_distance != 0 ? currentType.maximum_distance.ToString() : "";
                    maximumTravelDistanceTxtBox.CaretIndex = maximumTravelDistanceTxtBox.Text.Length;
                }
            }
        }

        

        private void OnPriceChanged(object sender, TextChangedEventArgs e)
        {
            if (selectedStationPricingId != -1)
            {
                TrytoStartEditing();
                Pricing pricing = currentType.Pricings.Where(p => p.station_id == selectedStationPricingId).Single();
                string price = priceBatteryTypeTxtBox.Text;
                double typePrice = 0;
                if (double.TryParse(price, out typePrice))
                {
                    pricing.price = typePrice;
                    currentInnerRow[3] = typePrice;
                }
                else if (price == "")
                {
                    pricing.price = 0;
                    currentInnerRow[3] = 0;
                }
                else
                {
                    priceBatteryTypeTxtBox.Text = pricing.price != 0 ? pricing.price.ToString() : "";
                    priceBatteryTypeTxtBox.CaretIndex = priceBatteryTypeTxtBox.Text.Length;
                }
                
            }
        }

        #endregion

        #region Account tab code


        #region Employee account tab code

        private void InitializeEmployeeAccountTab(IList<EmployeeAccount> allEmployeeAccounts)
        {
            this.allEmployeeAccounts = allEmployeeAccounts;

            ResetEmployeeAccountTab();

            IEnumerable<string> stationNames = allStations.Select(s => s.name);

            empStationComboBox.ItemsSource = stationNames;

            IList<string> roleNames = new List<string>();
            roleNames.Add("Administrator");
            roleNames.Add("Employee");

            empRoleComboBox.ItemsSource = roleNames;
            SwitchToEmployeeGUIState(GUIState.VIEWING);
        }

        private void ResetEmployeeAccountTab()
        {
            currentAccount = null;
            DataTable mainTable = new DataTable();
            mainTable.Columns.Add("Id", typeof(int));
            mainTable.Columns.Add("First name", typeof(string));
            mainTable.Columns.Add("Last name", typeof(string));
            mainTable.Columns.Add("Email", typeof(string));
            mainTable.Columns.Add("Phone nr", typeof(string));
            mainTable.Columns.Add("Role", typeof(string));
            mainTable.Columns.Add("Station managed", typeof(string));

            foreach (EmployeeAccount account in allEmployeeAccounts)
            {
                string role = account.employee_role == Role.Administrator ? "Administrator" : "Employee";
                string stationName = account.Station != null ? account.Station.name : "N/A";
                mainTable.Rows.Add(account.id, account.fname, account.lname, account.email, account.phone_nr, role, stationName);
            }

            
            employeeAccount_DataGrid.DataContext = mainTable;
            FillEmployeeBoxes(-1);
            if (employeeAccount_DataGrid.Columns.Count > 0)
            {
                employeeAccount_DataGrid.Columns[0].Visibility = Visibility.Hidden;
            }
        }

        private void OnEmployeeGridLoaded(object sender, RoutedEventArgs e)
        {
            if (employeeAccount_DataGrid.Columns.Count > 0)
            {
                employeeAccount_DataGrid.Columns[0].Visibility = Visibility.Hidden;
            }
        }

        private void OnEmployeeRowSelection(object sender, SelectionChangedEventArgs e)
        {
            DataGrid dg = (DataGrid)sender;
            
            if (dg.SelectedItem != null)
            {
                
                DataRowView row = (DataRowView)dg.SelectedItem;
                int id = (int)row[0];
                if (employeeAccountTabState == GUIState.EDITING)
                {
                    CancelEmployeeEditing();
                }
                currentAccount = null;// this is a hack, but there is too much stuff to do to make it proffesionally
                FillEmployeeBoxes(id);
                currentAccount = new EmployeeAccount();//end of hack
            }
            else
            {
                FillEmployeeBoxes(-1);
            }
        }

        private void SwitchToEmployeeGUIState(GUIState state)
        {
            batteryTypeTabState = state;
            switch (state)
            {
                case GUIState.ADDING:
                    SwitchToEmployeeAdding();
                    break;
                case GUIState.EDITING:
                    SwitchToEmployeeEditing();
                    break;
                case GUIState.VIEWING:
                    SwitchToEmployeeViewing();
                    break;
                default:
                    break;
            }
        }

        private void SwitchToEmployeeViewing()
        {
            employeeAccount_DataGrid.IsEnabled = true;
            DataRowView row = (DataRowView)employeeAccount_DataGrid.SelectedItem;
            employeeAccountTabState = GUIState.VIEWING;
            if (row != null)
            {
                int id = (int)row[0];
                FillEmployeeBoxes(id);
                currentAccount = allEmployeeAccounts.Where(ea => ea.id == id).Single();
                deleteAccount_Btn.IsEnabled = true;
            }
            else
            {
                deleteAccount_Btn.IsEnabled = false;
            }
            addNewAccount_Btn.Visibility = Visibility.Visible;
            saveAccountChanges_Btn.Content = "Save Changes";
            saveAccountChanges_Btn.IsEnabled = false;
            deleteAccount_Btn.Content = "Delete Account";
            
            empPasswordTxtBox.Visibility = Visibility.Hidden;
            empPasswordLbl.Visibility = Visibility.Hidden;
            empRepPasswordTxtBox.Visibility = Visibility.Hidden;
            empRepPasswordLbl.Visibility = Visibility.Hidden;
            changePassword_Btn.Visibility = Visibility.Visible;
        }

        private void SwitchToEmployeeEditing()
        {
            DataRowView row = (DataRowView) employeeAccount_DataGrid.SelectedItem;
            if(row != null)
            {
                employeeAccountTabState = GUIState.EDITING;
                int id = (int)row[0];
                //FillEmployeeBoxes(id);
                currentAccount = allEmployeeAccounts.Where(ea => ea.id == id).Select(x => new EmployeeAccount()
                {
                    id = x.id,
                    fname = x.fname,
                    lname = x.lname,
                    phone_nr = x.phone_nr,
                    email = x.email,
                    employee_role = x.employee_role,
                    Station = x.Station,
                    pass = null,
                    session_token = x.session_token,
                    username = x.username
                }).Single();
                addNewAccount_Btn.Visibility = Visibility.Hidden;
                saveAccountChanges_Btn.Content = "Save Changes";
                saveAccountChanges_Btn.IsEnabled = true;
                deleteAccount_Btn.Content = "Cancel";
            }
        }

        private void SwitchToEmployeeAdding()
        {
            employeeAccountTabState = GUIState.ADDING;
            employeeAccount_DataGrid.UnselectAll();
            employeeAccount_DataGrid.IsEnabled = false;
            currentAccount = new EmployeeAccount() { username = "", fname = "", lname = "", pass = "", email = "", phone_nr = "" } ;
            FillEmployeeBoxes(-2);
            addNewAccount_Btn.Visibility = Visibility.Hidden;
            saveAccountChanges_Btn.IsEnabled = true;
            saveAccountChanges_Btn.Content = "Save Account";
            deleteAccount_Btn.Content = "Cancel";
            deleteAccount_Btn.IsEnabled = true;

            empPasswordTxtBox.Visibility = Visibility.Visible;
            empPasswordLbl.Visibility = Visibility.Visible;
            empRepPasswordTxtBox.Visibility = Visibility.Visible;
            empRepPasswordLbl.Visibility = Visibility.Visible;
            changePassword_Btn.Visibility = Visibility.Hidden;
        }

        private void FillEmployeeBoxes(int employeeId)
        {
            if (employeeId == -1)
            {
                empFnameTxtBox.Text = "";
                empFnameTxtBox.IsEnabled = false;
                empLnameTxtBox.Text = "";
                empLnameTxtBox.IsEnabled = false;
                empPhoneTxtBox.Text = "";
                empPhoneTxtBox.IsEnabled = false;
                empEmailBox.Text = "";
                empEmailBox.IsEnabled = false;

                empRoleComboBox.SelectedIndex = -1;
                empRoleComboBox.IsEnabled = false;
                empStationComboBox.SelectedIndex = -1;
                empStationComboBox.IsEnabled = false;

                empUsernameTxtBox.Text = "";
                empUsernameTxtBox.IsEnabled = false;
                empRepPasswordTxtBox.Password = "";
                empPasswordTxtBox.Password = "";
                changePassword_Btn.IsEnabled = false;
                deleteAccount_Btn.IsEnabled = false;
            }
            else if (employeeId == -2)
            {
                empFnameTxtBox.Text = "";
                empFnameTxtBox.IsEnabled = true;
                empLnameTxtBox.Text = "";
                empLnameTxtBox.IsEnabled = true;
                empPhoneTxtBox.Text = "";
                empPhoneTxtBox.IsEnabled = true;
                empEmailBox.Text = "";
                empUsernameTxtBox.Text = "";
                empUsernameTxtBox.IsEnabled = true;
                empEmailBox.IsEnabled = true;

                empRoleComboBox.SelectedIndex = -1;
                empRoleComboBox.IsEnabled = true;
                empStationComboBox.SelectedIndex = -1;
                empStationComboBox.IsEnabled = true;

                empRepPasswordTxtBox.Password = "";
                empPasswordTxtBox.Password = "";
                changePassword_Btn.IsEnabled = true;
                deleteAccount_Btn.IsEnabled = true;
            }
            else
            {
                EmployeeAccount account = allEmployeeAccounts.Where(ea => ea.id == employeeId).Single();
                empFnameTxtBox.Text = account.fname;
                empFnameTxtBox.IsEnabled = true;
                empLnameTxtBox.Text = account.lname;
                empLnameTxtBox.IsEnabled = true;
                empPhoneTxtBox.Text = account.phone_nr;
                empPhoneTxtBox.IsEnabled = true;
                empEmailBox.Text = account.email;
                empEmailBox.IsEnabled = true;
                empUsernameTxtBox.Text = account.username;
                empUsernameTxtBox.IsEnabled = true;

                empRoleComboBox.SelectedIndex = (int) account.employee_role;
                empRoleComboBox.IsEnabled = true;
                
                if(account.Station != null)
                {
                    empStationComboBox.SelectedIndex = allStations.IndexOf(allStations.Where(s => s.id == account.Station.id).Single());
                    //Log("Selected station index => " + allStations.IndexOf(allStations.Where(s => s.id == account.Station.id).Single());
                }
                else
                {
                    empStationComboBox.SelectedItem = null;
                }

                empStationComboBox.IsEnabled = empRoleComboBox.SelectedIndex != 0;

                empRepPasswordTxtBox.Password = "";
                empPasswordTxtBox.Password = "";
                changePassword_Btn.IsEnabled = true;
                deleteAccount_Btn.IsEnabled = true;
            }
        }

        private void SaveNewEmployee()
        {
            if(IsEmployeeDataCorrect())
            {
                if(currentAccount.Station == null)
                {
                    currentAccount.station_id = null;
                }
                else
                {
                    currentAccount.station_id = currentAccount.Station.id;
                    currentAccount.Station = null;
                }
                
                using(ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.AddEmployeeAccount(currentAccount, usedAccount.session_token));
                }
                RefreshEmployeeAccounts();
                SwitchToEmployeeGUIState(GUIState.VIEWING);
            }
        }

        private void SaveEmployeeChanges()
        {
            if (IsEmployeeDataCorrect())
            {
                if(currentAccount.Station == null)
                {
                    currentAccount.station_id = null;
                }
                else
                {
                    currentAccount.station_id = currentAccount.Station.id;
                    currentAccount.Station = null;
                }

                using (ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.UpdateEmployeeAccount(currentAccount, usedAccount.session_token));
                }
                Log("Password was null => " + (currentAccount.pass == null));
                RefreshEmployeeAccounts();
                SwitchToEmployeeGUIState(GUIState.VIEWING);
            }
        }

        private void DeleteEmployeeAccount()
        {
            DataRowView row = (DataRowView)employeeAccount_DataGrid.SelectedItem;
            if(row != null)
            {
                int id = (int)row[0];
                EmployeeAccount ea = new EmployeeAccount() { id = id };
                using(ManagementServiceClient client = new ManagementServiceClient())
                {
                    DealWithExpiration(client.DeleteEmployeeAccount(ea, usedAccount.session_token));
                }
                RefreshEmployeeAccounts();
            }
        }

        private bool IsEmployeeDataCorrect()
        {
            string phoneRegex = @"\A\d+(-\d+)*\z";
            string emailRegex = @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
                @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$";
            if(!Regex.IsMatch(currentAccount.phone_nr, phoneRegex))
            {
                MessageBox.Show("The phone number has incorrect format!");
                return false;
            }
            if (currentAccount.phone_nr.Replace("-", "").Length < 8 && currentAccount.phone_nr.Replace("-", "").Length > 16 && currentAccount.phone_nr != "")
            {
                MessageBox.Show("Phone number must be at least 8 and max 16 digits!");
                return false;
            }
            if(!Regex.IsMatch(currentAccount.email, emailRegex))
            {
                MessageBox.Show("The email is incorrect!");
                return false;
            }
            if(currentAccount.fname.Length == 0)
            {
                MessageBox.Show("The first name must not be empty!");
                return false;
            }
            if (currentAccount.lname.Length == 0)
            {
                MessageBox.Show("The last name must not be empty!");
                return false;
            }
            if (empRoleComboBox.SelectedIndex == -1)
            {
                MessageBox.Show("You must select a role for employee!");
                return false;
            }
            if(empStationComboBox.SelectedItem == null && empRoleComboBox.SelectedIndex != 0)
            {
                MessageBox.Show("You must select a Station for a non administrator employee!");
                return false;
            }
            if (currentAccount.username.Length < 5)
            {
                MessageBox.Show("Username must be at least 5 letters long!");
                return false;
            }
            if (allEmployeeAccounts.Where(a => a.username == currentAccount.username && a.id != currentAccount.id).Count() > 0)
            {
                MessageBox.Show("Username already taken!");
                return false;
            }
            if(currentAccount.pass != null)
            {
                if (currentAccount.pass.Length < 8)
                {
                    MessageBox.Show("Password must be at least 8 characters long!");
                    return false;
                }
                if (currentAccount.pass != empRepPasswordTxtBox.Password && empRepPasswordTxtBox.Visibility == Visibility.Visible)
                {
                    MessageBox.Show("Password and it's repetition do not match!");
                    return false;
                }
            }
            

            return true;

            
        }

        private void CancelEmployeeAdding()
        {
            ResetEmployeeAccountTab();
            SwitchToEmployeeGUIState(GUIState.VIEWING);
        }

        private void CancelEmployeeEditing()
        {
            currentAccount = null;
            ResetEmployeeAccountTab();
            SwitchToEmployeeGUIState(GUIState.VIEWING);
        }

        private void OnDeleteAccount_BtnClicked(object sender, RoutedEventArgs e)
        {
            switch (employeeAccountTabState)
            {
                case GUIState.ADDING:
                    CancelEmployeeAdding();
                    break;
                case GUIState.EDITING:
                    CancelEmployeeEditing();
                    break;
                case GUIState.VIEWING:
                    DeleteEmployeeAccount();
                    break;
                default:
                    break;
            }
        }

        

        private void OnSaveAccount_BtnClicked(object sender, RoutedEventArgs e)
        {
            switch(employeeAccountTabState)
            {
                case GUIState.ADDING:
                    SaveNewEmployee();
                    break;
                case GUIState.EDITING:
                    SaveEmployeeChanges();
                    break;
                case GUIState.VIEWING:

                    break;
                default:
                    break;
            }
        }

        

        private void OnAddNewAccount_BtnClicked(object sender, RoutedEventArgs e)
        {
            SwitchToEmployeeGUIState(GUIState.ADDING);
        }

        private void TrytoStartEditingEmployee()
        {
            if(employeeAccountTabState == GUIState.VIEWING)
            {
                SwitchToEmployeeGUIState(GUIState.EDITING);
            }
        }

        private void OnFirstNameChangedEmployee(object sender, TextChangedEventArgs e)
        {
            if (currentAccount != null)
            {
                TrytoStartEditingEmployee();
                string regex = @"\A[a-zA-Z]*\z";
                string fname = empFnameTxtBox.Text;
                if (Regex.IsMatch(fname, regex))
                {
                    currentAccount.fname = fname;
                    if (employeeAccountTabState == GUIState.EDITING)
                    {
                        DataRowView row = (DataRowView)employeeAccount_DataGrid.SelectedItem;
                        if (row != null)
                        {
                            row[1] = fname;
                        }
                    }
                }
                else
                {
                    empFnameTxtBox.Text = currentAccount.fname;
                    empFnameTxtBox.CaretIndex = empFnameTxtBox.Text.Length;
                }
            }
        }

        private void OnLastNameChangedEmployee(object sender, TextChangedEventArgs e)
        {
            if (currentAccount != null)
            {
                TrytoStartEditingEmployee();
                string regex = @"\A[a-zA-Z]*\z";
                string lname = empLnameTxtBox.Text;
                if (Regex.IsMatch(lname, regex))
                {
                    currentAccount.lname = lname;
                    if (employeeAccountTabState == GUIState.EDITING)
                    {
                        DataRowView row = (DataRowView)employeeAccount_DataGrid.SelectedItem;
                        if (row != null)
                        {
                            row[2] = lname;
                        }
                    }
                }
                else
                {
                    empLnameTxtBox.Text = currentAccount.lname;
                    empLnameTxtBox.CaretIndex = empLnameTxtBox.Text.Length;
                }
            }
        }

        private void OnPhoneChangedEmployee(object sender, TextChangedEventArgs e)
        {
            if(currentAccount != null)
            {
                TrytoStartEditingEmployee();
                string regex = @"\A(\d+(-|\d)*)?\z";
                string phoneNr = empPhoneTxtBox.Text;
                if (Regex.IsMatch(phoneNr, regex))
                {
                    currentAccount.phone_nr = phoneNr;
                    if(employeeAccountTabState == GUIState.EDITING)
                    {
                        DataRowView row =  (DataRowView)employeeAccount_DataGrid.SelectedItem;
                        if(row != null)
                        {
                            row[4] = phoneNr;
                        }
                    }
                }
                else
                {
                    empPhoneTxtBox.Text = currentAccount.phone_nr;
                    empPhoneTxtBox.CaretIndex = empPhoneTxtBox.Text.Length;
                }
            }
        }

        

        private void OnEmailChangedEmployee(object sender, TextChangedEventArgs e)
        {
            if (currentAccount != null)
            {
                TrytoStartEditingEmployee();
                currentAccount.email = empEmailBox.Text;
                if (employeeAccountTabState == GUIState.EDITING)
                {
                    DataRowView row = (DataRowView)employeeAccount_DataGrid.SelectedItem;
                    if (row != null)
                    {
                        row[3] = currentAccount.email;
                    }
                }
            }
        }

        private void OnRoleChangedEmployee(object sender, SelectionChangedEventArgs e)
        {
            if (currentAccount != null)
            {
                TrytoStartEditingEmployee();
                currentAccount.employee_role = (Role) empRoleComboBox.SelectedIndex;
                if (employeeAccountTabState == GUIState.EDITING)
                {
                    DataRowView row = (DataRowView)employeeAccount_DataGrid.SelectedItem;
                    if (row != null)
                    {
                        row[5] = currentAccount.employee_role == Role.Administrator ? "Administrator" : "Employee";
                    }
                }
                if(currentAccount.employee_role == Role.Administrator)
                {
                    currentAccount.Station = null;
                    empStationComboBox.SelectedItem = null;
                    empStationComboBox.IsEnabled = false;
                }
                else
                {
                    empStationComboBox.IsEnabled = true;
                }
            }
        }

        private void OnStationChangedEmployee(object sender, SelectionChangedEventArgs e)
        {
            if (currentAccount != null && empStationComboBox.SelectedItem != null)
            {
                TrytoStartEditingEmployee();
                currentAccount.Station = allStations[empStationComboBox.SelectedIndex];
                if (employeeAccountTabState == GUIState.EDITING)
                {
                    DataRowView row = (DataRowView)employeeAccount_DataGrid.SelectedItem;
                    if (row != null)
                    {
                        row[6] = currentAccount.Station.name;
                    }
                }
            }
        }

        private void OnUsernameChangedEmployee(object sender, TextChangedEventArgs e)
        {
            if (currentAccount != null)
            {
                TrytoStartEditingEmployee();
                currentAccount.username = empUsernameTxtBox.Text;
            }
        }

        private void OnPasswordChangedEmployee(object sender, RoutedEventArgs e)
        {
            if (currentAccount != null)
            {
                TrytoStartEditingEmployee();
                currentAccount.pass = empPasswordTxtBox.Password;
            }
        }

        private void OnEmployeeSearch(object sender, TextChangedEventArgs e)
        {
            string name = employeeAccountSearchBox.Text.ToLower(); ;
            if (name == "")
            {
                employeeAccount_DataGrid.SelectedItem = null;
                return;
            }
            foreach (DataRowView row in employeeAccount_DataGrid.Items)
            {
                string fullName = (row[1].ToString() + " " + row[2].ToString()).ToLower();
                if (fullName.StartsWith(name))
                {
                    employeeAccount_DataGrid.SelectedItem = row;
                    return;
                }
            }
            employeeAccount_DataGrid.SelectedItem = null;
        }

        #endregion


        #region User account tab code

        private void InitializeUserAccountTab(IList<UserAccount> allUserAccounts)
        {
            this.allUserAccounts = allUserAccounts;
            DataTable mainTable = new DataTable();
            mainTable.Columns.Add("First name", typeof(string));
            mainTable.Columns.Add("Last name", typeof(string));
            mainTable.Columns.Add("Phone nr", typeof(string));
            mainTable.Columns.Add("Email", typeof(string));
            mainTable.Columns.Add("Registration date", typeof(DateTime));
            foreach (UserAccount account in allUserAccounts)
	        {
                mainTable.Rows.Add(account.fname, account.lname, account.phone_nr, account.email, account.registration_date);
	        }
           custAcc_DataGrid.DataContext = mainTable;
        }


        private void OnUserAccountRowSelected(object sender, SelectionChangedEventArgs e)
        {
            DataGrid grid = (DataGrid) sender;
            if(grid.SelectedItem != null)
            {
                DataRowView row = (DataRowView) grid.SelectedItem;
                custAccFnameTxtBox.Text = row[0].ToString();
                custAccLnameTxtBox.Text = row[1].ToString();
                custAccPhoneTxtBox.Text = row[2].ToString();
                custAccEmailBox.Text = row[3].ToString();
                custAccRegDateBox.Text = row[4].ToString();
            }
            else
            {
                custAccFnameTxtBox.Text = "";
                custAccLnameTxtBox.Text = "";
                custAccPhoneTxtBox.Text = "";
                custAccEmailBox.Text = "";
                custAccRegDateBox.Text = "";
            }
        }
        private void OnUserAccountSearched(object sender, TextChangedEventArgs e)
        {
            string name = custAccSearchBox.Text.ToLower();
            if(name == "")
            {
                custAcc_DataGrid.SelectedItem = null;
                return;
            }
            foreach(DataRowView row in custAcc_DataGrid.Items)
            {
                string fullName = (row[0].ToString() + " " + row[1].ToString()).ToLower();
                if(fullName.StartsWith(name))
                {
                    custAcc_DataGrid.SelectedItem = row;
                    return;
                }
            }
            custAcc_DataGrid.SelectedItem = null;
        }

        private void OnChangePassword_BtnClicked(object sender, RoutedEventArgs e)
        {
            if (currentAccount != null)
            {
                TrytoStartEditingEmployee();
                empPasswordTxtBox.Visibility = Visibility.Visible;
                empPasswordLbl.Visibility = Visibility.Visible;
                empRepPasswordTxtBox.Visibility = Visibility.Visible;
                empRepPasswordLbl.Visibility = Visibility.Visible;
                changePassword_Btn.Visibility = Visibility.Hidden;
            }
        }

        #endregion


        private string HourFormString(int time)
        {
            if(time < 0)
            {
                return "N/A";
            }
            int minutes = time % 60;
            int hours = time / 60;
            return String.Format("{0} h {1} min", hours, minutes);
        }

        #endregion

        private enum GUIState
        {
            ADDING,
            EDITING,
            VIEWING
        }

        private DataGridRow GetSelectedRow(DataGrid grid)
        {
            return (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(grid.SelectedItem);
        }

    

    }
}
